home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD-ROM Today - The Disc! 5
/
CD-ROM Today - The Disc (Issue 5)(November 1994).ISO
/
mac
/
Mac shareware
/
Applications
/
Alpha.5.81 folder
/
Help
/
XTCLs
< prev
Wrap
Text File
|
1994-09-21
|
8KB
|
226 lines
XTCLs (CopyRight 1992 by Tim Endres, modified by Pete Keleher)
The tcl external command interface is similar to the HyperCard external
command interface. Your code is a stand alone module that exists as a
resource in the common XTCL File or in a file by itself.
The advantage of having your XTCL in a separate file is the ability to have
access to your own set of resources that are always carried around with the
XTCL. The disadvantage is the cost of opening and close the XTCL's file
every time it is executed.
When Alpha is asked to execute the external command, it loads the resource
from the (1) application resource fork, (2) the XTCL File resource fork, or (3)
the resource fork of the optional file parameter. The resource is locked
down in memory, and called as a C function. The external command's C
code should begin as:
void
XTCLEntry(argc, argv, xpb)
long argc;
char **argv;
XTCLParmBlk *xpb;
The parameters are similar to what you would expect any C type program
to take, except for the xpb parameter block. This parameter block is your
link back into Alpha. Here is the structure:
typedef struct {
-> long version;
<-> long result;
<-> Handle resultH;
-> short cmdRefNum;
-> Handle cmdHandle;
-> Tcl_Interp *interp;
-> int (*eval)();
-> ModalFilterProcPtr modalproc;
- long reserved;
} XTCLParmBlk, *XTCLPBPtr;
The version field is passed in to indicate to the command what level of
functionality the tcl callback function supports, as well as indicate the
version of the parameter block data structure. The current version number
of defined by XTCL_CB_VERSION in the header file XTCL.h and is currently
0x00010001.
The result field is returned by the external command and is to be one of
the predefined constants in XTCL.h. The resultH field contains a handle
that is allocated by Alpha, with a length of zero, and passed to the external
command to contain the results of the command. The command will resize
the handle to hold its result, and copy the results into the handle's memory
before returning. The external command should never dispose of the
handle passed in resultH.
The cmdRefNum field is the file system reference number of the file
containing the XTCL command. Remember, this reference number may be
the application's reference number or the number of the XTCL File, if the
command was found in either of these locations. The external command
must never close this file.
The cmdHandle field is the handle to the code resource that contains the
external command itself. It will be locked. Do not unlock, move, modify, or
otherwise mutilate this memory!!!! Consider the handle and data READ
ONLY.
The interp field is a tcl interpreter pointer to the interpreter that called the
external command.
The eval field is a C procedure pointer to the callback routine to evaluate a
tcl statement. It is equivalent to using the eval tcl command. The callback is
used as follows:
result = (* xpb->eval)(xpb, sHandle, rHandle, stdoutHandle);
Where:
'xpb' is the parameter block pointer passed to the external command.
'sHandle' is a handle containing a null terminated string to be evaluated by the tcl
interpreter.
'rHandle' is a handle for the result of the command. It may be zero length, but if it is
not the results will be placed after the data already in the handle (as determined by
GetHandleSize). The result will not be null terminated, thus, GetHandleSize must
be used to determine the length of the result. This field may be NULL.
'stdoutHandle' is a handle for the standard output of the command. This is the
output generated by the print command and error reporting. It may be zero length,
but if it is not the results will be placed after the data already in the handle (as
determined by GetHandleSize). The results will not be null terminated, thus,
GetHandleSize must be used to determine the length of the result. This
field may be NULL.
The modalproc field is a procedure pointer to use in the
ModalFilterProcPointer field of ModalDialog and the like.
The reserved field is reserved.
Two example XTCLs created in Think C 5.04 are in the 'xtcls' directory.
The first merely returns a result based on its arguments. The second uses
the 'eval' field of the XTCLParmBlk to have Alpha evaluate a script which
adds a menu of all available sounds to Alpha's menubar. Selecting one of
the menu items calls back into the XTCL and plays the sound. A compiled
version of this XTCL is loaded into the Alpha binary. Use it by going to
the home directory in the Tcl shell (cd <cr>), and then typing "xtclcmd
sounds init".
When creating XTCLs in ThinkC:
1) Global data is fine, but static initialization of pointers to the
addresses of global data is not.
2) Except for the MacTraps library, all the libraries use global data. In
order to use them in your code resource, you must make a copy that
uses register a4 instead of a5 to reference global data. Make a copy
of the library you need, and change the project type to 'Code
Resource'.
3) Remember that 'argc' is passed as a long.
An external command in MPW C should look like:
#include "xtcl.h"
void
XTCLEntry(argc, argv, xpb)
int argc;
char **argv;
XTCLParmBlk *xpb;
{
char *ptr, state;
int i, length, slen;
xpb->result = TCL_OK;
length = GetHandleSize(xpb->resultH);
for (i=1; i < argc; i++)
slen += strlen(argv[i]) + 1;
SetHandleSize(xpb->resultH, slen+1);
state = HGetState(xpb->resultH);
HLock(xpb->resultH);
for (ptr=*xpb->resultH, i=1; i < argc; i++) {
strcat(ptr, argv[i]);
strcat(ptr, " ");
ptr += strlen(ptr);
}
HSetState(xpb->resultH, state);
}
And would be linked together with:
XTCL_echo ─ ╢
XTCL_echo.c.o
Echo '#' Linking XTCL_echo
Link -t "XTCL" -c "MPS " ╢
-rt "XTCL=2020" ╢
-sg "echo" ╢
-m XTCLEntry ╢
-o XTCL_echo ╢
XTCL_echo.c.o ╢
{CLibraries}StdCLib.o ╢
{Libraries}Interface.o
NOTE: The -sg "echo" option in the Link command will determined the
name of the code resource that is produced, and thus the name of the
external command. The -rt "XTCL=2020" option in the Link command
determines the resource type of the code generated, and its resource id.
The resource type must be XTCL, and the resource ID should try to be
unique, but is not critical.
Also remember that stand alone C code must not use global variables, and
must use the -b option when calling the C compiler to use string constants.
Finally, the following code fragment is an example of an XTCL that simply
calls the eval callback routine with its first argument to be evaluated.
#include "xtcl.h"
void
XTCLEntry(argc, argv, xpb)
int argc;
char **argv;
XTCLParmBlk *xpb;
{
long length;
int result;
Handle rHandle, sHandle;
char *script = argv[1];
xpb->result = TCL_OK;
length = strlen(script);
sHandle = NewHandle(length+1);
rHandle = NewHandle(0);
if (sHandle != NULL && rHandle != NULL)
{
strcpy(*sHandle, script);
result = (* xpb->eval)(xpb, sHandle, rHandle, NULL);
length = GetHandleSize(rHandle);
SetHandleSize(xpb->resultH, length + 1);
if (MemError() == noErr) {
memcpy(*xpb->resultH, *rHandle, GetHandleSize(rHandle));
* (*xpb->resultH + length) = '\0';
}
else
result = TCL_ERROR;
xpb->result = result;
}
if (sHandle != NULL)
DisposHandle(sHandle);
if (rHandle != NULL)
DisposHandle(rHandle);
}
NOTE: Pascal programmers will need to link with the Pascal glue code to
work. The glue code provides a C entry that will call your Pascal routine for
the XTCL. It also provides glue to callback the interpreter for evaluation.
Please see the example sources and makefile for further details.